
//
// 版权所有 (c) 2021-2023 JR
//
// 特此免费授予获得本软件的任何人以处理本软件的权利，但须遵守以下条件：在所有副本或重要部分的软件中必须包括上述版权声明和本许可声明。
//
// 软件按“原样”提供，不提供任何形式的明示或暗示的保证，包括但不限于对适销性、适用性和非侵权的保证。
// 在任何情况下，作者或版权持有人均不对任何索赔、损害或其他责任负责，无论是因合同、侵权或其他方式引起的，与软件或其使用或其他交易有关。

using EMC.VISITOR.Core;
using EMC.VISITOR.Core.Service;
using AspNetCoreRateLimit;
using Furion;
using Furion.SpecificationDocument;
using Furion.VirtualFileServer;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using OnceMi.AspNetCore.OSS;
using System;
using System.Net;
using System.Net.Mail;
using Yitter.IdGenerator;
using Newtonsoft.Json.Converters;
using System.Globalization;
using Microsoft.AspNetCore.Http.Features;
using Newtonsoft.Json.Serialization;
using EMC.VISITOR.Web.Core;

namespace EMC.VISITOR.Tasks;

public class Startup : AppStartup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // 配置选项
        services.AddProjectOptions();

        // 缓存注册
        services.AddCache();
        // SqlSugar
        services.AddSqlSugar();
        // JWT
        services.AddJwt<JwtHandler>(enableGlobalAuthorize: true);
        // 允许跨域
        services.AddCorsAccessor();
        // 远程请求
        services.AddRemoteRequest();
        // 任务队列
        services.AddTaskQueue();
        // 任务调度
        services.AddSchedule(options =>
        {
            options.AddPersistence<DbJobPersistence>(); // 添加作业持久化器
        });
        // 脱敏检测
        services.AddSensitiveDetection();

        // Json序列化设置
        static void SetNewtonsoftJsonSetting(JsonSerializerSettings setting)
        {
            setting.DateTimeZoneHandling = DateTimeZoneHandling.Local;
            setting.DateFormatString = "yyyy-MM-dd HH:mm:ss"; // 时间格式化
            setting.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; // 忽略循环引用

            //setting.ContractResolver = new CamelCasePropertyNamesContractResolver(); // 解决动态对象属性名大写
            // setting.NullValueHandling = NullValueHandling.Ignore; // 忽略空值
            // setting.Converters.AddLongTypeConverters(); // long转string（防止js精度溢出） 超过16位开启
            //setting.MetadataPropertyHandling = MetadataPropertyHandling.Ignore; // 解决DateTimeOffset异常
            //setting.DateParseHandling = DateParseHandling.None; // 解决DateTimeOffset异常
            //setting.Converters.Add(new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }); // 解决DateTimeOffset异常
        };

        services.AddControllersWithViews(r => r.AllowEmptyInputInBodyModelBinding = true)
            .AddAppLocalization()
            .AddNewtonsoftJson(options =>
            {
                SetNewtonsoftJsonSetting(options.SerializerSettings);
                options.SerializerSettings.Converters.AddClayConverters();
            })
            //.AddXmlSerializerFormatters()
            //.AddXmlDataContractSerializerFormatters()
            .AddInjectWithUnifyResult<JRResultProvider>();

        

        // ElasticSearch
        services.AddElasticSearch();

        // 配置Nginx转发获取客户端真实IP
        // 注1：如果负载均衡不是在本机通过 Loopback 地址转发请求的，一定要加上options.KnownNetworks.Clear()和options.KnownProxies.Clear()
        // 注2：如果设置环境变量 ASPNETCORE_FORWARDEDHEADERS_ENABLED 为 True，则不需要下面的配置代码
        services.Configure<ForwardedHeadersOptions>(options =>
        {
            options.ForwardedHeaders = ForwardedHeaders.All;
            options.KnownNetworks.Clear();
            options.KnownProxies.Clear();
        });

 

        //使用Rabbit做为Furion事件总线的事件源
        services.AddRabbitMqByEventBus();

        services.SapLoadICUSetUp();
        services.SapConnectionSetUp();

        // OSS对象存储
        var ossOpt = App.GetOptions<OSSProviderOptions>();
        services.AddOSSService(Enum.GetName(ossOpt.Provider), "OSSProvider");

        // 电子邮件
        var emailOpt = App.GetOptions<EmailOptions>();
        services.AddFluentEmail(emailOpt.DefaultFromEmail, emailOpt.DefaultFromName)
            .AddSmtpSender(new SmtpClient(emailOpt.Host, emailOpt.Port)
            {
                EnableSsl = emailOpt.EnableSsl,
                UseDefaultCredentials = emailOpt.UseDefaultCredentials,
                Credentials = new NetworkCredential(emailOpt.UserName, emailOpt.Password)
            });

        // 模板引擎
        services.AddViewEngine();

        services.AddSingleton(typeof(ResilienceClientFactory), sp =>
        {
            var logger = sp.GetRequiredService<ILogger<ResilienceHttpClient>>();
            var httpcontextAccesser = sp.GetRequiredService<IHttpContextAccessor>();
            var retryCount = 1;
            var exeptionCountAllowedBeforeBreaking = 1;
            return new ResilienceClientFactory(logger, httpcontextAccesser, retryCount, exeptionCountAllowedBeforeBreaking);
        });
        services.AddSingleton<IHttpClient>(sp =>
        {
            return sp.GetRequiredService<ResilienceClientFactory>().GetResilienceHttpClient();
        });


        // 即时通讯
        services.AddSignalR(options =>
            {
                options.KeepAliveInterval = TimeSpan.FromSeconds(5);
            })
            .AddNewtonsoftJsonProtocol(options => SetNewtonsoftJsonSetting(options.PayloadSerializerSettings));

        // 系统日志
        services.AddLoggingSetup();

        services.Configure<FormOptions>(x =>
        {
            x.ValueLengthLimit = int.MaxValue;
            x.MultipartBodyLengthLimit = int.MaxValue; // In case of multipart
        });

        // 雪花Id
        YitIdHelper.SetIdGenerator(App.GetOptions<SnowIdOptions>());

     
        // 验证码
        services.AddCaptcha();
        // 控制台logo
        services.AddConsoleLogo();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseForwardedHeaders();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseForwardedHeaders();
            app.UseHsts();
        }
        //允许跨域查看服务器静态资源
        app.UseStaticFiles(new StaticFileOptions
        {
            ServeUnknownFileTypes = true,
            OnPrepareResponse = (c) =>
            {
                c.Context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
                c.Context.Response.Headers.Add("Cache-Control", "no-cache");
            }
        });
        app.UseRouting();
        app.UseCorsAccessor();
        app.UseAuthentication();
        app.UseAuthorization();
        // 任务调度看板
        app.UseScheduleUI();
        app.UseInject(string.Empty);
    }
}